#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "program.h"
#include "shell.h"

static uint8_t _iobits = 1;
static bool _capslock = false;
static bool _numlock = false;
static bool _scrolllock = false;

static char _input[64] = { 0 };

static struct sio_device* _sio = NULL;
static struct kbd_device* _kbd = NULL;
static struct screen_device* _screen = NULL;
static struct digit_io_device* _digit = NULL;

void shell_init(
struct sio_device *sio,
struct kbd_device *kbd,
struct screen_device *screen,
struct digit_io_device* digit)
{
    _sio = sio;
    _kbd = kbd;
    _screen = screen;
    _digit = digit;
}

void shell_run(void)
{
    // clear screen
    _screen->clear();
    _screen->print("Welcome to z80 computer!\n");
    _screen->print("CPU: Z84C0010PEC 10.00MHz\n");
    _screen->print("ROM: 32KB\n");
    _screen->print("RAM: 32KB\n");
    _screen->print("----------------------------------------\n");

  for (;;) {
    // wait input
    _screen->input(_input, sizeof(_input), _kbd);

    // echo input
    _sio->write(_input, strlen(_input));

    if (strcmp(_input, "hi") == 0) {
      
      // welcome program
       _screen->print("hi, I am z80 machine, built by bitrowz.\n");

    } else if (strcmp(_input, "clear") == 0) {

      // clear screen program
      _screen->clear();

    } else if (strcmp(_input, "help") == 0) {
      
      // help program
      _screen->print("commands:\n");
      _screen->print("  hi\n");
      _screen->print("  clear\n");
      _screen->print("  sum\n");
      _screen->print("  bilibili\n");
      _screen->print("  help\n");

    } else if (strcmp(_input, "sum") == 0) {
      // sum test program
      bzz80_sum(_screen, _sio);

    } else if (strcmp(_input, "chess") == 0) {
      
      // chess test program
      bzz_chess(_screen, _sio);
      
    } else {
      // invalid command
      _screen->print("invalid command\n");

    }

    // screen update
    _screen->update();

    // led refresh
    _iobits <<= 1;
    _iobits = _iobits > 0 ? _iobits : 1;
    _digit->write(_iobits);
  }
}